Xi-Language Reference: Expressions

    • Explaining Notes
    • Numbers and Variables
    • Function Calls
    • Calculation Expressions (Operations)
    • Comparison Expressions
    • Assignment and extended Assignment Expressions

    Explaining Notes

    After we have pointed out what a number, a string and identifiers are you certainly ask yourself what the Parser does with this input. What would you do with two numbers? You may have the idea to multiply these numbers or divide them, or add them and devid the result by a third number. That is what the expressions are for. Roughly spoken, expressions are all types of calculations that are possible in Xi, they are the main part of the language definition. Consequently it is not surprising that this chapter is so big.

    Numbers and Variables

    One of the basic expressions is simply a number, it is a variable or, to be more exact, the name of a variable. Therefore
                 <num>
                 <id>       (not follow by a '(')
    
    are valid expressions. The result of these expressions is simply the value of the number respectively the variable. Also a single string can be an expression:
                 <string>
    

    Brand new are the mathematical constant expressions:

                 ~<id>
    
    The Parser simply searches for a known constant <id> and replaces it by the corresponding value. Known constants are:
                 ~pi      Yust Pi (that thing with the diameter and the circumfence)
                 ~e       Yust e  (the Euler constant)
                 ~log2e   this is log_2 e
                 ~log10e  this is log_10 e
                 ~ln      this is ln 2 respectively log_e 2
                 ~ln10    this is ln 10 respectively log_e 10
                 ~pi_2    this is pi/2
                 ~pi_4    this is pi/4
                 ~1_pi    this is 1/pi
                 ~2_pi    this is 2/pi
                 ~sqrt2   this is sqrt(2)
                 ~sqrt1_2 this is 1/sqrt(2)
    
    ... and a couple more out of math.h .

    If the variable is an array there are two equivalent ways to get an element of this array:

                 <id> [ <expr> , <expr> , ...]
                 <id> [ <expr> ] [ <expr> ]...
    
    Where the ... means at least one or more, and <expr> is another expression. Of course strings are not allowed at this point, but you can make any type of calculation here. For example: a[5,10],a[5,2*5],a[5][10] are valid expressions with the same result (see Calculation Expressions below).

    Sometimes you may not only want a single element but a whole subarray of a bigger array. For this purpose a special index access does exist:

                 <id> [ <expr1> .. <expr2> ,... ]
                 <id> [ <expr1> .. <expr2> : <expr3> ,... ]
                 <id> [ * ,... ]
    
    The * represents the whole row where <expr1>..<expr2> <expr1> defines the lower bound, <expr2> the upperbound of a row and <expr1>..<expr2>:<expr3>. You can additionally define a stepsize <expr3> for that row (at the moment <expr3> must be greater or equal one, and <expr2> should be greater or equal <expr1>).

    If this index access still dosn't satisfy you Xi can also perform a where access:

                 <id> [ where <expr> ]
    
    Here the result of <expr> is an integer array containing the indices of the array <id>. Usually <expr> is a Comparison between arrays.

    Function calls

    An Expression may also be the result of a function:
                 <id> ( )
    
    The () are essential at this point, they are the only way for the Parser to distinguish between a variable and a function. If and <id> are followed by a '(' . The Parser seeks for a function with that name or otherwise for a variable.

    The above rule describes the function call to a function with no parameter. Usually a function may have several parameters that have to be set by arguments in the function call:

                 <id> ( <expr1> , <expr2> ,...)
    
    <expr1>,<expr2>,... are the arguments of the functions.

    So far we are C compatible. In C the order of the function arguments is fixed. There is actually no way to set the first parameter with the second argument and vice versa. For this purpose Xi has named arguments:

                 <id> ( \ <id1> = <expr1> , \ <id2> = <expr2> ,...)
    
    That means: The parameter <id1> of function <id> is set to the result of <expr1>, the parameter <id2>is set to the result of <expr2> and so on. In this way you can control the order of calculations of a function call's arguments (if you need dirty stuff like this). Xi first calculates <expr1>, then <expr2> and so on.

    Furthermore the named arguments are useful if the function has flags.

                 <id> ( \ <id1> , \ <id2> ,...)
    
    will be translated to
                 <id> ( \ <id1> = 1 , \ <id2> = 1 ,...)
    
    which means that the parameters <id1>, <id2>,... of function <id> are all set to one respectively to true (since Xi has no boolean type a nonzero integer is true and zero is false. See Compare Expressions for more detail)

    Calculation Expressions

    The expressions given above are very simple,with the exception of function calls there are no real calculations. Now we define which operations between expressions are valid. First of all Xi understands all standard arithmetical operations, i.e.:
                 - <expr>          (unary minus)
                 <expr1> + <expr2>
                 <expr1> - <expr2>
                 <expr1> * <expr2>
                 <expr1> / <expr2>
                 ( <expr> )
    
    Note that these operators have the same precendencs as in C, i.e.: An expression 4*5+1 will be evaluated as (4*5)+1, and 4/-1+5 will be evaluated as (4/(-1))+5. Also the operators are left-associative, i.e.: An expression 1-2-3 will be evaluated as (1-2)-3 and 4/5*6 will be evaluated as (4/5)*6. If you want more informations consult a C introduction. Please keep in mind though that in Xi all operations also work on arrays e.g. you can add an array with a scalar or two arrays with the same dimensions.

    In Addition to these standard operations Xi has a special matrix multiplication for arrays:

                 <expr1> # <expr2>
                 <expr1> ## <expr2>
                 <expr1> ### <expr2>
                          .
                          .
                          .
    
    The first operation is a simple matrix multiplication between an nxm matrix <expr1> and a mxk matrix <expr2>, the second operation will multiply a (...,m,k)-tensor with a (m,k,...)-tensor by summing over the two inner indices. The third will multiply a (...,n,m,k)-tensor with a (n,m,k,...)-tensor by summing over the three inner indizes and so on.

    If you want to calculate with complex numbers, you certainly want to enter the real and imaginary part of this number directly.

                 ( <expr1> , <expr2> )
    
    This expression also works if <expr1> and <expr2> are arrays with the same dimenstions.

    If you want to build up an array element by element, Xi offers you the folling expression:

                 { <expr1> , <expr2> , ... , <exprn> }
    
    If <expr1> to <exprn> are scalars (i.e. no arrays) the above expression will generate a n-dimensional vector with corresponding entries. If <expr1> to <exprn> are all m-dimensional vectors the expression will generate a nxm matrix and so on. In this way it is possible to construct the wildest arrays you can think of.

    Sometimes it comes handy to cast a double value into an integer an vice versa. In Xi there are two equivalent ways to cast a value to a specific type:

                 ( <type> ) <expr>
                 <type> ( <expr> )
    
    The first possibility is C compatible the second is the C++ way - pick one.

    Comparison Expressions

    In Xi comparisons are also operations and strictly spoken belong to the previous section. But in the most cases comparisons are very dump operations, the only result is an integer zero (false) or a integer one (true). Let's be more precise:
                 <expr1> == <expr2>
                 <expr1> != <expr2>
                 <expr1> < <expr2>
                 <expr1> <= <expr2>
                 <expr1> > <expr2>
                 <expr1> >= <expr2>
    
    are all implented comparisons between two expressions. If <expr1> and <expr2> are scalars the above expressions should be clear, they can be found in every common C-introduction. If one or both are arrays Xi will compare an array with a scalar or two arrays element by element. The result is an array of integers filled with the indices of the array where the comparison is true.

    Besides the pure comparisons there also exist logical operations usually used in connection with comparisons:

                <expr1> && <expr2>
                <expr1> || <expr2>
    
    If <expr1> and <expr2> are simple comparisons between scalars these two operators act in the same way as in C. If <expr1> and <expr2> are both comparisons between arrays && (||) takes the union (cut) of the two resulting index arrays (see above).

    Assignment Expressions

    In the previous sections we used variables as input for an expression only. Till today we don't know any way to change the value of variable, that is what the assignment expressions are vor. The basic assignment expression is
                <id> = <expr>
    
    which sets the variable <id> to the result of <expr>. The result of the whole expression is the new value of the Variable. Note that = is a right-associative operator, i.e. an input a=b=c=3 will be interpreted as a=(b=(c=3)) or, in human words, first set variable c to 3. Then set variable b to the result of this assignment (which is the new value of c and therefore also 3). Finally the a to the result of the last assignment (which is the new value of b; 3). Consequently a, b and c are all set to the value 3.

    Assignments are also defined to set one or more elements of an array:

                <id> [ <indx> ] = <expr>
                <id> [ where <expr> ] = <expr>
    
    Where <indx> means a list of indices which may contain ranges.

    Like in C there the folling operations that directly act on variables exist:

                <id> += <expr>
                <id> -= <expr>
                <id> *= <expr>
                <id> /= <expr>
                <id> ++
                <id> --
                ++ <id>
                -- <id>
    
    All these operations act in the same way as in C except that in Xi they also work on arrays. +=,-=,*= and /= add, subtract, multiply respectively divide the variable <id> by the result of <expr>. As in the previous case the result of the whole expression is the new value of <id>. ++ and -- increments respectively decrements the variable <id> by one. The result of this operation depends on whether ++ or -- stands before or after <id>. In the first case the result is the new value of <id> in the latter it is the old value of <id>. For a more detailed description have a look into a C-introduction.

    The operation from above also works with elements of an array:

                <id> [ <indx> ] += <expr>
                <id> [ where <expr> ] += <expr>
                <id> [ <indx> ] -= <expr>
                <id> [ where <expr> ] -= <expr>
                <id> [ <indx> ] *= <expr>
                <id> [ where <expr> ] *= <expr>
                <id> [ <indx> ] /= <expr>
                <id> [ where <expr> ] /= <expr>
                <id> [ <indx> ] ++
                <id> [ where <expr> ] ++
                <id> [ <indx> ] --
                <id> [ where <expr> ] --
                ++ <id> [ <indx> ]
                ++ <id> [ where <expr> ]
                -- <id> [ <indx> ]
                -- <id> [ where <expr> ]
    

    In addition to these standard assignments Xi also has an extended assignment to set the values of several variables at once:

                [ <id1> , <id2> ,... ] = [ <expr1> , <expr2> ,..
    . ]
    
    With this the variable <id1> will be set to the result of <expr1>, <id2> to the result of <expr2> and so on. The result of the whole expression is the new value of <id1>. This assignment is not useful under normal circumstances with the exception of a function having more than one return value.
                [ <id1> , <id2> ,... ] = <id_f> ( <args> )
    
    Here the Variables <id1>, <id2>, ... will be set to the results of the function <id_f ( args means the arguments of this functions; see Function calls for more detail).


    © 1995 by Bodo Junglas, Klaus Spanderen and Fabian Weis
    - Last revised: May 30 1996